package com.dz51.core.validate.context;  

import java.lang.reflect.Method;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang.StringUtils;

import com.dz51.core.validate.annotation.ParamValidater;
import com.dz51.core.validate.annotation.ValidateMapping;
import com.dz51.core.validate.exception.InitValidateException;
import com.dz51.core.validate.util.ClassUtil;
  
public class UrlMethodValidateMapping {
    
    
    private UrlMethodValidateMapping() {
    }
    
    private static UrlMethodValidateMapping urlMethodValidateMapping = new UrlMethodValidateMapping();
    
    public static UrlMethodValidateMapping getInstance(){
        return urlMethodValidateMapping;
    }

    /**
     * 方法与校验规则的映射（多个方法参数）
     */
    private static final Map<Method, ParamValidater[]> mappingRules = new ConcurrentHashMap<Method, ParamValidater[]>();
    
    /**
     * 根据规则返回校验规则
     * @param handlerMethod
     * @return
     */
    public ParamValidater[] getMappingRule(Method method) {
        if(mappingRules == null || mappingRules.isEmpty()){
            return null;
        }
        return mappingRules.get(method);
    }
    
    /**
     * 加载参数规则
     * @return
     */
    public boolean initMappingRules(String basePackage){
        
        if(basePackage == null || basePackage.trim().length() == 0){
            throw new InitValidateException("校验规则初始化：basePackage配置的参数名不能为空");
        }
        String[] paths = basePackage.split(",");
        if(paths == null || paths.length == 0){
            throw new InitValidateException("校验规则初始化：basePackage配置的参数名不能为空");
        }
        
        Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
        
        for (String path : paths) {
            Package pack = Package.getPackage(path);
            Set<Class<?>>  clses = ClassUtil.getClasses(pack);
            if(clses != null){
                classes.addAll(clses);
            }
        }
        
        for (Class<?> clses : classes) {
            final Method[] methods = clses.getMethods();
            for (Method method : methods) {
                if(method.isAnnotationPresent(ValidateMapping.class)){
                    
                    ValidateMapping validateMapping = method.getAnnotation(ValidateMapping.class);
                    
                    ParamValidater[] paramValidaters = validateMapping.value();
                    
                    for (ParamValidater paramValidater : paramValidaters) {
                        //参数名校验
                        if(StringUtils.isBlank(paramValidater.name())){
                            throw new InitValidateException("校验规则初始化：方法" + method.getName() + "配置的参数名不能为空");
                        }
                        
                        if(paramValidater.minLen() < 0){
                            throw new InitValidateException("校验规则初始化：方法" + method.getName() + "参数" + paramValidater.name() + "的minLen属性配置有误");
                        }
                        
                        if(paramValidater.maxLen() < 0){
                            throw new InitValidateException("校验规则初始化：方法" + method.getName() + "参数" + paramValidater.name() + "的maxLen属性配置有误");
                        }
                        
                        if(paramValidater.maxLen() < paramValidater.minLen()){
                            throw new InitValidateException("校验规则初始化：方法" + method.getName() + "参数" + paramValidater.name() + "的maxLen属性要不小于minLen属性");
                        }
                        
                        if(paramValidater.validators() == null || paramValidater.validators().length == 0){
                            throw new InitValidateException("校验规则初始化：方法" + method.getName() + "参数" + paramValidater.name() + "的validators属性不能为空");
                        }
                        
                    }
                    mappingRules.put(method, paramValidaters);
                }
            }
        }
        return true;
    }
}
